home *** CD-ROM | disk | FTP | other *** search
- PAGE 60
- ; *********************************************************************
- ; ** KISS Protocol Program for VADCG TNC+ and KISS V1.03 **
- ; ** VADCG TNC1 with 2732 EPROM mod **
- ; ** By: Mike Bruski, AJ9X 08FEB87 **
- ; *********************************************************************
-
- ; Change History:
- ; When Who What
- ; 26JAN87 AJ9X Initial Version (V1.00)
- ; 31JAN87 AJ9X Removed auto baud rate detection &
- ; interval timer driven by 8253 (V1.01)
- ; 07FEB87 AJ9X Send last character and release cell
- ; on transmitted async. frames (V1.02)
- ; 08FEB87 AJ9X Disabled early end of frame interrupt
- ; from 8273 to prevent transmitter
- ; shutdown prior to sending CRC and
- ; closing flag (V1.03)
- PAGE
-
- ;
- ; 8250 SIO Controller Equates
-
- ; Registers:
-
- RBR EQU 0 ; RECEIVE BUFFER REGISTER [R]
- THR EQU 0 ; TRANSMIT HOLDING REGISTER [W]
- DLL EQU 0 ; DRIVER LATCH (LSB) [W]
- DLM EQU 1 ; DRIVER LATCH (MSB) [W]
- IER EQU 1 ; INTERRUPT ENABLE REGISTER [W]
- IIR EQU 2 ; INTERRUPT IDENTIFICATION REGISTER [R]
- LCR EQU 3 ; LINE CONTROL REGISTER [R/W]
- MCR EQU 4 ; MODEM CONTROL REGISTER [R/W]
- LSR EQU 5 ; LINE STATUS REGISTER [R/W]
- MSR EQU 6 ; MODEM STATUS REGISTER [R/W]
-
- ; Equates for Interrupt Enable Register
-
- ERI EQU 00000001B ; ENABLE RECEIVE DATA INTERRUPTS
- ETI EQU 00000010B ; ENABLE TRANSMIT DATA INTERRUPTS
- ELI EQU 00000100B ; ENABLE LINE STATUS INTERRUPTS
- EMI EQU 00001000B ; ENABLE MODEM STATUS INTERRUPTS
-
- ; Equates for Line Status Register
-
- DR EQU 00000001B ; DATA READY
- OE EQU 00000010B ; OVERRUN ERROR
- PE EQU 00000100B ; PARITY ERROR
- FE EQU 00001000B ; FRAMING ERROR
- BI EQU 00010000B ; BREAK INTERRUPT
- THRE EQU 00100000B ; TRANSMIT HOLDING REGISTER EMPTY
- TSRE EQU 01000000B ; TRANSMIT SHIFT REGISTER EMPTY
-
- ; Equates for Modem Status Register
-
- DCTS EQU 00000001B ; DELTA CLEAR-TO-SEND
- DDSR EQU 00000010B ; DELTA DATA-SET-READY
- TERI EQU 00000100B ; TRAILING EDGE OF RING INDICATOR
- DCD EQU 00001000B ; DELTA CARRIER DETECT
- TCTS EQU 00010000B ; TERMINAL CLEAR-TO-SEND
- TDSR EQU 00100000B ; TERMINAL DATA-SET-READY
- TRI EQU 01000000B ; TERMINAL RING INDICATOR
- TCD EQU 10000000B ; TERMINAL CARRIER DETECT
-
- ; Equates for Line Control Register
-
- D5 EQU 00000000B ; WORD LENGTH = 5 BITS
- D6 EQU 00000001B ; WORD LENGTH = 6 BITS
- D7 EQU 00000010B ; WORD LENGTH = 7 BITS
- D8 EQU 00000011B ; WORD LENGTH = 8 BITS
- S1 EQU 00000000B ; STOP BITS = 1
- S2 EQU 00000100B ; STOP BITS = 2
- NP EQU 00000000B ; NO PARITY
- PEN EQU 00001000B ; PARITY ENABLE
- OP EQU 00000000B ; ODD PARITY
- EP EQU 00010000B ; EVEN PARITY SELECT
- STP EQU 00100000B ; STICK PARITY
- SB EQU 01000000B ; SET BREAK
- DLA EQU 10000000B ; DIVISOR LATCH ACCESS
-
- ; Equates for Modem Control Register
-
- ADTR EQU 00000001B ; ASYNCHRONOUS DATA-TERMINAL-READY
- ARTS EQU 00000010B ; ASYNCHRONOUS REQUEST-TO-SEND
- OUT1 EQU 00000100B ; ASYNCHRONOUS CARRIER DETECT (LOOP=RI)
- OUT2 EQU 00001000B ; NO CONNECTION ON VADCG (LOOP=CD)
- LOOP EQU 00010000B ; LOOPBACK DIAGNOSTIC ENABLE
-
- ; Equates for Interrupt Identification Register
-
- AIPM EQU 00000001B ; ASYNC INT. PENDING MASK
- ; INTERRUPT IS PENDING IF NOT SET
- IIM EQU 00000110B ; INTERRUPT IDENTIFICATION MASK
- RLSI EQU 00000110B ; RECEIVER LINE STATUS INTERRUPT
- RDAI EQU 00000100B ; RECEIVED DATA AVAILABLE INTERRUPT
- TREI EQU 00000010B ; TRANSMIT HOLDING REG. EMPTY INTERRUPT
- MSI EQU 00000000B ; MODEM STATUS INTERRUPT
- PAGE
-
- ;
- ; 8273 HDLC Controller Equates
-
- ; Registers:
-
- STAT73 EQU 10H ; STATUS REGISTER [R]
- CMND73 EQU 10H ; COMMAND REGISTER [W]
- PARM73 EQU 11H ; PARAMETER REGISTER [W]
- RESL73 EQU 11H ; RESULTS REGISTER [R]
- TEST73 EQU 12H ; TEST REGISTER [W]
- TXIR73 EQU 12H ; TRANSMIT INTERRUPT RESULTS REGISTER[R]
- RXIR73 EQU 13H ; RECEIVE INTERRUPT RESULTS REGISTER [R]
- TXDR73 EQU 18H ; TRANSMIT DATA REGISTER [W]
- RXDR73 EQU 20H ; RECEIVE DATA REGISTER [R]
-
- ; Equates for STAT73
-
- TXIRA EQU 00000001B ; TRANSMIT INTERRUPT RESULTS AVAILABLE
- RXIRA EQU 00000010B ; RECEIVE INTERRUPT RESULTS AVAILABLE
- TINTP EQU 00000100B ; TRANSMIT INTERRUPT STILL PENDING
- RINTP EQU 00001000B ; RECEIVE INTERRUPT STILL PENDING
- CRBF EQU 00010000B ; COMMAND RESULTS BUFFER FULL
- CPBF EQU 00100000B ; COMMAND PARAMETER BUFFER FULL
- CBF EQU 01000000B ; COMMAND BUFFER FULL
- CBSY EQU 10000000B ; COMMAND BUFFER BUSY
-
- ; Equates for TXIR73
-
- EXI EQU 00001100B ; EARLY TRANSMIT INTERRUPT
- FTC EQU 00001101B ; FRAME TRANSMISSION COMPLETE
- DMAU EQU 00001110B ; DMA UNDERRUN (not used)
- CTSE EQU 00001111B ; CLEAR-TO-SEND ERROR
- ATC EQU 00010000B ; ABORT TRANSMISSION COMPLETE
-
- ; Equates for RXIR73
-
- CRCE EQU 00000011B ; CRC ERROR
- FAD EQU 00000100B ; FRAME ABORT DETECTED
- IFD EQU 00000101B ; IDLE FLAG DETECTED
- EOPD EQU 00000110B ; EOP DETECTED (not used)
- SFD EQU 00000111B ; SHORT FRAME DETECTED (< 32 BITS)
- DMAO EQU 00001000B ; DMA OVERRUN
- MBO EQU 00001001B ; MEMORY BUFFER OVERFLOW
- CDF EQU 00001010B ; CARRIER DETECT FAILURE
- RIO EQU 00001011B ; RECEIVE INTERRUPT OVERRUN
-
- ; Equates for PORT A (input)
-
- MCTS EQU 00000001B ; MODEM CLEAR-TO-SEND
- MCD EQU 00000010B ; MODEM CARRIER DETECT
- PA2 EQU 00000100B ; SPARE PORT INPUT
- PA3 EQU 00001000B ; SPARE PORT INPUT
- PA4 EQU 00010000B ; SPARE PORT INPUT
-
- ; Equates for PORT B (output)
-
- MRTS EQU 00000001B ; MODEM REQUEST-TO-SEND
- PB1 EQU 00000010B ; SPARE PORT OUTPUT
- PB2 EQU 00000100B ; SPARE PORT OUTPUT
- PB3 EQU 00001000B ; SPARE PORT OUTPUT
- PB4 EQU 00010000B ; SPARE PORT OUTPUT
- FD EQU 00100000B ; FLAG DETECT
- PAGE
-
- ;
- ; 8253 Interval Timer Equates (VDS-1 only)
-
- ; Registers:
-
- PIT0 EQU 28H ; COUNTER PORT 0 (8273 BAUD RATE)
- PIT1 EQU 29H ; COUNTER PORT 1 (8085 TRAP)
- PIT2 EQU 2AH ; COUNTER PORT 2
- ITCP EQU 2BH ; INTERVAL TIMER CONTROL PORT
-
- ; Equates for ITCP (control word)
-
- ; Register selection field
- C0 EQU 00000000B ; COUNTER 0
- C1 EQU 01000000B ; COUNTER 1
- C2 EQU 10000000B ; COUNTER 2
-
- ; Read/Load control field
- LC EQU 00000000B ; LATCH COUNT
- RLL EQU 00010000B ; READ/LOAD LSB ONLY
- RLM EQU 00100000B ; READ/LOAD MSB ONLY
- RLB EQU 00110000B ; READ/LOAD LSB FIRST, MSB NEXT
-
- ; Mode control field
- MD0 EQU 00000000B ; MODE 0, TIMED INTERRUPT
- MD1 EQU 00000010B ; MODE 1, RETRIGGERABLE ONE SHOT
- MD2 EQU 00000100B ; MODE 2, RATE GENERATOR
- MD3 EQU 00000110B ; MODE 3, SQUARE WAVE GENERATOR
- MD4 EQU 00001000B ; MODE 4, SOFTWARE TRIGGERED STROBE
- MD5 EQU 00001010B ; MODE 5, HARDWARE TRIGGERED STROBE
-
- ; Counter Type field
- BIN EQU 00000000B ; 16 BIT BINARY
- BCD EQU 00000001B ; 4 DECADE BCD
-
- ; Equates for PIT0 (Synchronous Baud Rate Values)
-
- SBR9600 EQU 4 ; 9600 baud
- SBR4800 EQU 8 ; 4800 baud
- SBR2400 EQU 16 ; 2400 baud
- SBR1200 EQU 32 ; 1200 baud (default)
- SBR600 EQU 64 ; 600 baud
- SBR300 EQU 128 ; 300 baud
-
- ; Equates for PIT1 (Cyclic Timer) - NOT USING THIS YET
- ; Input = 38.4Khz from pin 4 of U40
-
- MS100 EQU 3840 ; 100ms timer value
- MS50 EQU 1920 ; 50ms timer value
- MS20 EQU 768 ; 20ms timer value
- MS10 EQU 384 ; 10ms timer value (default)
-
- ; Use these guys for S/W timing (now for all VADCG & ASHBY)
- IC100 EQU 2297 ; Interval count for 100ms
- IC10 EQU 230 ; Interval count for 10ms
-
- ; Equates for PIT2 (Random Number Generator)
- ; Input = 38.4Khz from pin 4 of U40
-
- SEED EQU 32767
- PAGE
-
- ;
- ; 8085 CPU Interrupt Mask Register Equates
-
- ACD EQU 00000001B ; RST5.5, ASYNC. INTERRUPTS DISABLED
- STD EQU 00000010B ; RST6.5, SYNC. XMTR INT. DISABLED
- SRD EQU 00000100B ; RST7.5, SYNC. RCVR INT. DISABLED
- MSE EQU 00001000B ; INTERRUPT MASK ENABLED
-
- ;
- ; Special Character Equates
- EOS EQU 00H
- LF EQU 0AH
- CR EQU 0DH
- COMMA EQU 2CH
- PERIOD EQU 2EH
- FEND EQU 0C0H
- FESC EQU 0DBH
- TFEND EQU 0DCH
- TFESC EQU 0DDH
-
- ;
- ; End Action (Event) Flags
- SRFC EQU 00000001B ; SYNC. RECEIVER FRAME COMPLETION
- ARFC EQU 00000010B ; ASYNC. RECEIVER FRAME COMPLETION
- STFC EQU 00000100B ; SYNC. TRANSMITTER FRAME COMPLETION
- ATFC EQU 00001000B ; ASYNC. TRANSMITTER FRAME COMPLETION
- EXTI EQU 00010000B ; EXPIRED TIMER
- SRDD EQU 00100000B ; SYNC. RECEIVER DISCARDING DATA
- ARDD EQU 01000000B ; ASYNC. RECEIVER DISCARDING DATA
-
- ;
- ; Miscellaneous Equates
- WDVAL EQU 220 ; DEFAULT WATCH DOG DELAY FOR 1200 BAUD
- PAGE
-
- TRUE EQU -1
- FALSE EQU NOT TRUE
- ;
- ; Static Random Access Memory (SRAM) Equates
-
- ; LORAM HIRAM CONFIGURATION
- ;
- ; 1000H 1FFFH *ASHBY with 2716 ROMs or Standard VADCG
- ; 2000H 2FFFH ASHBY with 2732 ROMs
- ; 7000H 7FFFH VADCG with California memory mods
- ; 8000H 8FFFH VADCG with early AMRAD memory mods
- ; 8000H 9FFFH VADCG with VDS-1 (8K RAM)
- ; 8000H FFFFH VADCG with VDS-1 (32K RAM)
- ; 4000H 4FFFH VADCG with VADCG 2732 modification
-
- TNCPLUS EQU TRUE
- TNC32 EQU FALSE
-
- IF TNCPLUS
- VECTORS EQU 0FF00H ; Restart and interrupt vectors in RAM
- MONENT EQU 0 ; Monitor entry point
- LORAM EQU 0C000H ; Beginning of RAM
- HIRAM EQU 0DFFFH ; End of RAM
- ELSE
- LORAM EQU 1000H ; BEGINNING OF SRAM
- HIRAM EQU 1FFFH ; END OF SRAM
- ENDIF
-
- STACK EQU LORAM+64H ; BEGINNING OF PROGRAM STACK
- TICKCNT EQU STACK+1 ; TICK COUNT FOR TNC+
- EA$FLG EQU STACK+2 ; END ACTION FLAGS
-
- ; Interval Timer Variables
- PVAL EQU EA$FLG+1 ; PERSISTENCE VALUE
- SVAL EQU PVAL+1 ; SLOT-TIME VALUE
- RVAL EQU SVAL+1 ; RELAY DELAY VALUE
- TVAL EQU RVAL+1 ; SQUELCH TAIL DELAY VALUE
- TICKS EQU TVAL+1 ; TICK COUNTER FOR S/W TIMING
- IT$FLG EQU TICKS+2 ; 0 = INACTIVE, 1 = ACTIVE
- IT$VAL EQU IT$FLG+1 ; CURRENT TIMER VALUE
- IT$STA EQU IT$VAL+2 ; CURRENT TIMER STATE
-
- ; Asynchronous Receiver Variables
- AR$HC EQU IT$STA+1 ; CURRENT FRAME HEAD
- AR$BP EQU AR$HC+2 ; CURRENT BUFFER POINTER
- AR$FSZ EQU AR$BP+2 ; CURRENT FRAME SIZE
- AR$FH EQU AR$FSZ+2 ; COMPLETED FRAME HEAD
- AR$FS EQU AR$FH+2 ; COMPLETED FRAME SIZE
- AR$STA EQU AR$FS+2 ; CURRENT MACHINE STATE
-
- ; Asynchronous Transmitter Variables
- AT$BP EQU AR$STA+1 ; CURRENT BUFFER POINTER
- AT$QS EQU AT$BP+2 ; QUEUE SIZE
- AT$QR EQU AT$QS+1 ; QUEUE READ POINTER
- AT$QW EQU AT$QR+2 ; QUEUE WRITE POINTER
- AT$STA EQU AT$QW+2 ; CURRENT MACHINE STATE
-
- ; Synchronous Receiver Variables
- SR$HC EQU AT$STA+1 ; CURRENT FRAME HEAD
- SR$BP EQU SR$HC+2 ; CURRENT BUFFER POINTER
- SR$FR EQU SR$BP+2 ; CURRENT FRAME RESULTS
- SR$STA EQU SR$FR+1 ; CURRENT MACHINE STATE
-
- ; Synchronous Transmitter Variables
- ST$BP EQU SR$STA+1 ; CURRENT BUFFER POINTER
- ST$FR EQU ST$BP+2 ; CURRENT FRAME RESULTS
- ST$QS EQU ST$FR+1 ; QUEUE SIZE
- ST$QR EQU ST$QS+1 ; QUEUE READ POINTER
- ST$QW EQU ST$QR+2 ; QUEUE WRITE POINTER
-
- ; Synchronous Command Buffers
- SRACT EQU ST$QW+2 ; RECEIVER ACTIVATION COMMAND
- STACT EQU SRACT+4 ; TRANSMITTER ACTIVATION COMMAND
-
- ; Asynchronous Transmitter Queue
- AT$QT EQU STACT+4 ; TOP OF QUEUE
- AT$QB EQU AT$QT+(2*64) ; BOTTOM OF QUEUE
-
- ; Synchronous Transmitter Queue
- ST$QT EQU AT$QB+2 ; TOP OF QUEUE
- ST$QB EQU ST$QT+(4*64) ; BOTTOM OF QUEUE
-
- ; Buffer area
- FL$HC EQU ST$QB+4
- NCELL EQU (HIRAM-FL$HC+2)/128
- BAREA EQU (HIRAM-NCELL*128)+1 ; BEGINNING OF BUFFER AREA
- NLIST EQU BAREA-2 ; # OF AVAILABLE CELLS IN FREE LIST
- PAGE
-
- BASE EQU 0
- ORG BASE ; PROGRAM ORIGIN
-
- IF NOT TNCPLUS
- ;
- ; Here we begin -
- ; A good place to start is with the interrupt vectors
-
- ;
- ; RST0 - [H/W AND S/W INTERRUPT]
- ; ENTER HERE ON POWER UP AND WHEN THE RESET
- ; BUTTON IS SMASHED TO INITIALIZE THE H/W
- ; AND MEMORY. MIGHT ALSO VECTOR HERE IN S/W
- ; IF EVERYTHING IS SO MESSED UP THE TNC CAN'T
- ; FUNCTION CORRECTLY.
-
- RST0 EQU $ ; RESTART (WARM & COLD)
- JMP INIT
-
- ORG BASE+08H
-
- ;
- ; RST1 - [S/W INTERRUPT]
- ; ENTER HERE TO RETURN FROM AN INTERRUPT. THE FIRST
- ; ITEM ON THE STACK WILL BE A RETURN ADDRESS TO THE
- ; RST INSTRUCTION WHICH GOT US HERE SO IT GETS WASTED.
- ; NEXT THE PROGRAM STATUS WORD (ACCUMULATOR & FLAGS)
- ; ARE RESTORE, INTERRUPTS ARE RE-ENABLED AND THE REST
- ; IS HISTORY.
-
- RST1 EQU $
- POP PSW ; PURGE BOGUS ADDRESS FROM STACK
- POP PSW ; RESTORE PROGRAM STATUS WORD
- EI ; UNGATE INTERRUPTS
- RET ; RETURN TO POINT OF INTERRUPT
-
- ORG BASE+10H
-
- ;
- ; RST2 - [S/W INTERRUPT]
- ; NO FUNCTION
-
- RST2 EQU $
- RET
-
- ORG BASE+18H
-
- ;
- ; RST3 - [S/W INTERRUPT]
- ; NO FUNCTION
-
- RST3 EQU $
- RET
-
- ORG BASE+20H
-
- ;
- ; RST4 - [S/W INTERRUPT]
- ; NO FUNCTION
-
- RST4 EQU $
- RET
-
- ORG BASE+24H
-
- ;
- ; TRAP - [NON MASKABLE H/W INTERRUPT]
- ; NOT USED
-
- TRAP EQU $
- EI
- RET
-
- ORG BASE+28H
-
- ;
- ; RST5 - [S/W INTERRUPT]
- ; NO FUNCTION
-
- RST5 EQU $
- RET
-
- ORG BASE+2CH
-
- ;
- ; RST5.5 - [MASKABLE H/W INTERRUPT]
- ; VECTOR HERE WHEN A SIGNAL IS DETECTED ON PIN 9 OF
- ; THE 8085. THE 8250 WILL ASSERT THIS PIN WHEN ONE
- ; OF THE FOLLOWING OCCURS; TRANSMIT BUFFER EMPTY,
- ; RECEIVE CHARACTER AVAILABLE, RECEIVER OVERRUN,
- ; RECEIVER PARITY ERROR, RECEIVER FRAMING ERROR,
- ; BREAK INTERRUPT, DELTA CTS, DELTA DSR, RING INDICATE
- ; OR RECEIVE LINE SIGNAL DETECT.
-
- RST55 EQU $
- JMP AIRC ; GOTO ASYNC. INTERRUPT RESPONSE CODE
-
- ORG BASE+30H
-
- ;
- ; RST6 - [S/W INTERRUPT]
- ; NO FUNCTION
-
- RST6 EQU $
- RET
-
- ORG BASE+34H
-
- ;
- ; RST6.5 - [MASKABLE H/W INTERRUPT]
- ; VECTOR HERE WHEN A SIGNAL IS DETECTED ON PIN 8 OF
- ; THE 8085. THE 8273 WILL ASSERT THIS PIN WHEN THE
- ; SYNCHRONOUS TRANSMITTER REQUIRES SERVICE.
-
- RST65 EQU $
- JMP STIRC ; GOTO SYNC. XMTR INTERRUPT RESPONSE CODE
-
- ORG BASE+38H
-
- ;
- ; RST7 - [S/W INTERRUPT]
- ; NO FUNCTION
-
- RST7 EQU $
- RET
-
- ORG BASE+3CH
-
- ;
- ; RST7.5 - [MASKABLE H/W INTERRUPT]
- ; VECTOR HERE WHEN A SIGNAL IS DETECTED ON PIN 7 OF
- ; THE 8085. THE 8273 WILL ASSERT THIS PIN WHEN THE
- ; SYNCHRONOUS RECEIVER REQUIRES SERVICE.
-
- RST75 EQU $
- JMP SRIRC ; GOTO SYNC. RCVR INTERRUPT RESPONSE CODE
-
- ENDIF
-
- PAGE
- ;
- ; Initialize Hardware
- ; Branch here for critical S/W errors or H/W reset
-
- ; Begin by reseting the 8250, 8253, and 8273
- INIT EQU $
- DI ; GATE INTERRUPTS
- LXI SP,STACK ; SET STACK POINTER
- CALL INIT73 ; Initialize 8273
- XRA A ; A <-- 0 [ 4 tcy]
- OUT MCR ; DROP 8250 DTR & RTS [10 tcy]
- OUT IER ; KILL 8250 INTERRUPTS [10 tcy]
- IN RBR ; FLUSH THE 8250 INPUT REGISTER
- IN RBR
-
- ; H/W is now in an acceptable state, continue
-
- ; Now clear SRAM
- LXI D,HIRAM ; DE <-- HIGH SRAM ADDRESS
- LXI H,LORAM ; HL <-- LOW SRAM ADDRESS
-
- INIT1 EQU $
- MVI M,0 ; CLEAR NEXT LOCATION
- INX H ; INCREMENT POINTER
- MOV A,D ; A <-- MSB OF HIGH ADDRESS
- CMP H
- JNZ INIT1 ; IF (D <> H) GOTO INIT1
- MOV A,E ; A <-- LSB OF HIGH ADDRESS
- CMP L
- JNZ INIT1 ; IF (E <> L) GOTO INIT1
- MVI M,0 ; ZERO LAST RAM LOCATION
-
- ; Initialize linked list of free cells
- MVI A,NCELL ; A <-- # OF CELLS
- STA NLIST ; SAVE IN SRAM
- MOV B,A ; NOW MOVE CELL COUNT TO B
- LXI D,BAREA ; DE <-- ADDRESS OF BUFFER AREA
- DCR B ; SO THAT LAST CELL IS 0
- INIT2 EQU $
- LXI H,128 ; HL <-- CELL SIZE
-
- IF TNC32
- MOV A,B
- ANI 0FH
- CPI 8
- JZ INIT2A
- LXI H,0C80H
- INIT2A:
- ENDIF
-
- DAD D ; HL <-- ADDRESS OF NEXT CELL
- XCHG ; DE <-- NEXT, HL <-- CURRENT
- MOV M,E ; CURRENT GETS LSB OF NEXT
- INX H
- MOV M,D ; FOLLOWED BY MSB OF NEXT
- DCR B ; B <-- B-1
- JNZ INIT2 ; IF (B <> 0) GOTO INIT2
-
- ; Initialize state variables
- MVI A,7
- STA AR$STA
- MVI A,0FFH
- STA AT$STA
-
- ; Initialize queue variables
- LXI H,AT$QT
- SHLD AT$QR
- SHLD AT$QW
- LXI H,ST$QT
- SHLD ST$QR
- SHLD ST$QW
-
- ; Initialize miscellaneous variables
- LXI H,0C002H ; GENERAL RECEIVE COMMAND (8273)
- SHLD SRACT
- LXI H,330 ;*;; MAXIMUM ALLOWABLE PACKET LENGTH
- SHLD SRACT+2
- LXI H,0C802H ; TRANSMIT FRAME COMMAND (8273)
- SHLD STACT
- LXI H,BAREA ; H <-- ADDRESS OF FREE CELL AREA
- SHLD FL$HC ; ESTABLISH FREE LIST HEAD CELL
- LXI H,MS10 ; H <-- CONSTANT FOR 10MS S/W TIMING
- SHLD TICKS ; PRELOAD S/W COUNT VARIABLE
- MVI A,2 ; DEFAULT SQUELCH TAIL DELAY (20ms)
- STA TVAL
- MVI A,5 ; DEFAULT SLOT-TIME DELAY (50ms)
- STA SVAL
- MVI A,30 ; DEFAULT RELAY DELAY (300ms)
- STA RVAL
- MVI A,128 ; DEFAULT PERSISTENCE VALUE (0.5)
- STA PVAL
-
- IF TNCPLUS
- ; Install interrupt vectors
- MVI A,0C3H
- STA VECTORS+2CH ; 8250 interrupt
- LXI H,AIRC
- SHLD VECTORS+2DH
-
- STA VECTORS+34H ; 8273 transmit interrupt
- LXI H,STIRC
- SHLD VECTORS+35H
-
- STA VECTORS+3CH ; 8273 receive interrupt
- LXI H,SRIRC
- SHLD VECTORS+3DH
-
- STA VECTORS+38H ; 8255 interrupt
- LXI H,MONENT
- SHLD VECTORS+39H
-
- ELSE
-
- ; Establish baud rate for asynchronous port
- LXI H,32 ; CONSTANT FOR 4800 BAUD
- MVI A,DLA ; A <-- DIVISOR LATCH ACCESS FLAG
- OUT LCR ; WRITE LINE CONTROL REGISTER
- MOV A,L ; A <-- LSB OF BAUD RATE CONSTANT
- OUT DLL ; WRITE DIVISOR LATCH LSB
- MOV A,H ; A <-- MSB OF SAME
- OUT DLM ; WRITE DIVISOR LATCH MSB
- MVI A,NP+D8+S2 ; NO PARITY, 8 DATA BITS, 2 STOP BITS
- OUT LCR ; WRITE LINE CONTROL REGISTER
- ENDIF
-
- ;**********************************************************************
- ; The following code segment is for VDS-1 users only!!!
- ; Erase ';*;' in columns 1 thru 3 to assemble this segment.
- ; Establish baud rate for synchronous port
- ;*; MVI A,C0+RLB+MD3+BIN ; 8253 MODE CONTROL WORD
- ;*; OUT ITCP ; WRITE INTERVAL TIMER CONTROL PORT
- ;*; LXI H,SBR1200 ; CONSTANT FOR 1200 BAUD
- ;*; MOV A,L ; A <-- LSB
- ;*; OUT PIT0 ; WRITE
- ;*; MOV A,H ; A <-- MSB
- ;*; OUT PIT0 ; WRITE
-
- ; Activate the random number generator.
- ;*; MVI A,C2+RLB+MD3+BIN ; MODE CONTROL WORD
- ;*; OUT ITCP ; WRITE
- ;*; LXI H,SEED ; COUNTER VALUE
- ;*; MOV A,L ; A <-- LSB
- ;*; OUT PIT2 ; WRITE
- ;*; MOV A,H ; A <-- MSB
- ;*; OUT PIT2 ; WRITE
- ;**********************************************************************
-
- ; Asynchronous controller activation
- ; RST5.5 to CPU is enabled first
- MVI A,ERI+ELI+EMI ; RECEIVE AND LINE STATUS ENABLE
- OUT IER ; WRITE INTERRUPT ENABLE REGISTER
- MVI A,ADTR+ARTS+OUT1 ; DTR, RTS, & CD FOR HOST
- OUT MCR ; WRITE MODEM CONTROL REGISTER
-
- CALL GCELL ; GET A FREE CELL
- XCHG ; HL <-- CELL POINTER
- SHLD SR$BP ; ESTABLISH NEW POINTERS
- SHLD SR$HC
- MVI M,0 ; RESET FORWARD POINTER
- INX H ; ADVANCE POINTER
- MVI M,0
- MVI A,MSE ; UNGATE RST5.5,RST6.5, & RST7.5
- DB 30H ; 8085 SIM INSTRUCTION
- LXI H,SRACT ; SYNC. RECEIVER ACTIVATION COMMAND
- CALL SCMDOT
-
- ; LIGHTS! CAMERA! ACTION!
- EI
- PAGE
-
- ; TNC Executive Routine
-
- EXEC EQU $
- LDA EA$FLG ; A <-- END ACTION FLAGS
- ANA A
- JNZ EXEC2 ; IF (FLAGS SET) GOTO EXEC2
- LDA IT$FLG ; A <-- TIMER CONTROL FLAG
- ORA A
- JNZ EXEC1 ; IF (TIMER ACTIVE) GOTO EXEC1
- LXI H,RPA ; HL <-- READ PORT A COMMAND
- CALL SCMDOT ; ISSUE COMMAND
- CALL SRSLIN ; READ RESULTS
- ANI MCD ; MASK MODEM CARRIER DETECT
- JNZ EXEC ; IF (CHANNEL BUSY) GOTO EXEC
- LDA ST$QS ; A <-- SYNC. XMTR QUEUE SIZE
- ORA A
- JZ EXEC ; IF (EMPTY QUEUE) GOTO EXEC
-
- ;**********************************************************************
- ; The following code segment is for VDS-1 users only!!!
- ; Remove ';*; in column 1 thru 3 to assemble this segment.
- ; ASHBY and non-VDS VADCGs are rendered totally non-persistent
- ;*; MVI A,C2+RLL ; READ CONTROL WORD
- ;*; OUT ITCP ; WRITE INTERVAL TIMER CONTROL PORT
- ;*; IN PIT2 ; READ LSB OF TIMER (OUR RANDOM #)
- ;*; MOV B,A ; COPY TO B FOR NOW
- ;*; LDA PVAL ; A <-- PERSISTENCE VALUE
- ;*; SUB B
- ;*; JNC A5$S0A ; IF (RANDOM < PVAL) GOTO A5$S0A
- ;**********************************************************************
- IF TNCPLUS
- LDA TICKCNT ; Get TNC+ 75Hz. timer count
- MOV B,A ; Copy to B for now
- LDA PVAL ; A<-- Persistence value
- SUB B
- JNC A5$S0A ; If (Random < Pval) go to A5$S0A
- ENDIF
-
-
-
- LDA SVAL ; A <-- SLOT-TIME VALUE
- MOV L,A ; COPY TO L
- XRA A
- MOV H,A ; EXTEND 16 BITS
- SHLD IT$VAL ; ESTABLISH TIMER VALUE
- STA IT$STA ; RECORD NEW STATE
- INR A
- STA IT$FLG ; ACTIVATE TIMER
- JMP EXEC
-
- ; Active timer processing
- EXEC1 EQU $
- LHLD TICKS ; HL <-- S/W TIMER COUNT
- DCX H ; DECREMENT
- SHLD TICKS ; RECORD NEW COUNT
- MOV A,L ; A <-- LSB OF COUNT
- ORA H ; MSB
- JNZ EXEC ; IF (NOT 0) GOTO EXEC
- LXI H,MS10 ; 10ms TIMER CONSTANT
- SHLD TICKS ; RELOAD COUNT
- LHLD IT$VAL ; HL <-- INTERVAL TIMER VALUE
- DCX H ; DECREMENT TIMER
- SHLD IT$VAL ; RECORD IT
- MOV A,L
- ORA H
- JNZ EXEC ; IF (NOT EXPIRED) GOTO EXEC
- STA IT$FLG ; DEACTIVATE TIMER
- DI ; GATE INTERRUPTS MOMENTARILY
- LDA EA$FLG ; A <-- END ACTION FLAGS
- ORI EXTI ; FLAG EXPIRED TIMER
- STA EA$FLG ; RECORD FLAGS
- EI ; UNGATE
- JMP EXEC ; BACK TO TOP
-
- ; End action processing
- EXEC2 EQU $
- RAR
- JC EX$A1 ; IF (SRFC) GOTO EX$A1
- RAR
- JC EX$A2 ; IF (ARFC) GOTO EX$A2
- RAR
- JC EX$A3 ; IF (STFC) GOTO EX$A3
- RAR
- JC EX$A4 ; IF (ATFC) GOTO EX$A4
- RAR
- JC EX$A5 ; IF (EXPIRED TIMER) GOTO EX$A5
- RAR
- JC EX$A6 ; IF (SRDD) GOTO EX$A6
- RAR
- JC EX$A7 ; IF (ARDD) GOTO EX$A7
- JMP EXEC ; CONTINUE
-
-
-
-
-
- ; Here for synchronous receiver frame completion
- EX$A1 EQU $
- LHLD SR$HC ; HL <-- FRAME HEAD
- PUSH H ; PRESERVE HL
- DI ; GATE INTERRUPTS MOMENTARILY
- CALL GCELL ; GET A FREE CELL
- EI ; UNGATE
- JZ EX$A11 ; IF (BUFFERS FULL) GOTO EX$A11
- XCHG ; HL <-- CELL POINTER
- SHLD SR$BP ; ESTABLISH NEW POINTERS
- SHLD SR$HC
- MVI M,0 ; RESET FORWARD POINTER
- INX H ; ADVANCE POINTER
- MVI M,0
- LXI H,SRACT ; HL <-- SYNC. RCVR ACTIVATION COMMAND
- CALL SCMDOT ; ISSUE COMMAND
- EX$A11 EQU $
- MVI B,0FFH-SRFC ; B <-- FLAG MASK
- DI ; GATE INTERRUPTS MOMENTARILY
- LDA EA$FLG ; A <-- END ACTION FLAGS
- ANA B ; MASK OUT SRFC
- STA EA$FLG ; WRITE FLAGS
- EI ; UNGATE
- POP H ; RESTORE FRAME HEAD
- LDA SR$FR ; A <-- FRAME RESULTS
- CPI 0E0H ; EXPECTED RESULTS
- JNZ EX$A12 ; IF (BAD FRAME) GOTO EX$A12
- CALL LATQ ; ELSE LINK FRAME TO ASYNC. XMIT QUEUE
- JMP EXEC
- EX$A12 EQU $
- CALL FCHN ; RELEASE BAD FRAME
- JMP EXEC
-
-
-
-
-
- ; Here for asynchronous receiver frame completion
- EX$A2 EQU $
- MVI B,0FFH-ARFC ; B <-- FLAG MASK
- DI ; GATE INTERRUPTS MOMENTARILY
- LDA EA$FLG ; A <-- END ACTION FLAGS
- ANA B ; MASK OUT ARFC
- STA EA$FLG ; WRITE FLAGS
- EI ; UNGATE
- LHLD AR$FS ; HL <-- FRAME SIZE
- MOV B,H ; COPY TO BC
- MOV C,L
- LHLD AR$FH ; HL <-- FRAME HEAD
- CALL LSTQ ; LINK FRAME TO SYNC. XMIT QUEUE
- MVI A,ADTR+ARTS+OUT1 ; DTR, RTS, AND CD FOR HOST
- OUT MCR ; WRITE MODEM CONTROL REGISTER
- JMP EXEC
-
-
-
-
-
- ; Here for synchronous transmitter frame completion
- EX$A3 EQU $
- MVI B,0FFH-STFC ; B <-- FLAG MASK
- DI ; GATE INTERRUPTS MOMENTARILY
- LDA EA$FLG ; A <-- END ACTION FLAGS
- ANA B ; MASK OUT STFC
- STA EA$FLG ; WRITE FLAGS
- EI ; UNGATE
- LDA ST$QS ; A <-- QUEUE SIZE
- ORA A
- JZ EX$A32 ; IF (EMPTY QUEUE) GOTO EX$A32
- DCR A ; ELSE DECREMENT COUNT
- STA ST$QS ; WRITE NEW COUNT
- LHLD ST$QR ; HL <-- QUEUE READ POINTER
- LXI D,-ST$QB ; DE <-- QUEUE BOTTOM ADDRESS
- PUSH H
- DAD D
- POP H ; RESTORE READ POINTER
- JNC EX$A31 ; IF (NOT BOTTOM) GOTO EX$A31
- LXI H,ST$QT ; HL <-- QUEUE TOP ADDRESS
- EX$A31 EQU $
- MOV C,M ; LSB OF FRAME SIZE
- INX H ; ADVANCE POINTER
- MOV B,M ; MSB OF FRAME SIZE
- INX H
- MOV E,M ; LSB OF FRAME HEAD
- INX H
- MOV D,M ; MSB OF FRAME HEAD
- INX H
- SHLD ST$QR ; RECORD NEW POINTER
- XCHG ; HL <-- FRAME HEAD
- SHLD ST$BP ; RECORD IT
- LXI H,STACT+2 ; HL <-- SYNC. XMTR PARAMETER POINTER
- MOV M,C ; COPY LSB OF FRAME SIZE
- INX H ; ADVANCE POINTER
- MOV M,B ; COPY MSB OF FRAME SIZE
- LXI H,STACT ; HL <-- SYNC. XMTR ACTIVATION COMMAND
- CALL SCMDOT ; ISSUE COMMAND
- ; SET WATCHDOG TIMER HERE (LETS GO FOR A DEFAULT VALUE INITIALLY)
- LXI H,WDVAL ; HL <-- DEFAULT WATCHDOG TIMER
- SHLD IT$VAL ; RECORD IT
- MVI A,1
- STA IT$FLG ; ENABLE TIMER
- INR A ; NEW STATE
- STA IT$STA ; RECORD IT
- JMP EXEC
- ; Queue empty, disable synchronous transmitter (deactivate RTS)
- EX$A32 EQU $
- LXI H,DARTS ; HL <-- DEACTIVATE RTS COMMAND
- CALL SCMDOT ; ISSUE COMMAND
- LDA TVAL ; A <-- SQUELCH TAIL TIMER VALUE
- MOV L,A ; COPY VALUE TO L
- XRA A
- MOV H,A ; EXTEND 16 BITS
- SHLD IT$VAL ; RECORD IT
- INR A ; A <-- 1
- STA IT$FLG ; ACTIVATE TIMER
- MVI A,3 ; NEW STATE
- STA IT$STA ; RECORD IT
- JMP EXEC
-
-
-
-
-
- ; Here for asynchronous transmitter frame completion
- EX$A4 EQU $
- MVI B,0FFH-ATFC ; B <-- FLAG MASK
- DI ; GATE INTERRUPTS MOMENTARILY
- LDA EA$FLG ; A <-- END ACTION FLAGS
- ANA B ; MASK OUT ATFC
- STA EA$FLG ; WRITE FLAGS
- EI ; UNGATE
- LDA AT$QS ; A <-- QUEUE SIZE
- ORA A
- JZ EXEC ; IF (EMPTY QUEUE) GOTO EXEC
- DCR A ; ELSE DECREMENT COUNT
- STA AT$QS ; WRITE NEW COUNT
- LHLD AT$QR ; HL <-- QUEUE READ POINTER
- LXI D,-AT$QB ; DE <-- QUEUE BOTTOM ADDRESS
- PUSH H ; PRESERVE HL
- DAD D
- POP H ; RESTORE QUEUE POINTER
- JNC EX$A41 ; IF (NOT BOTTOM) GOTO EX$A41
- LXI H,AT$QT ; HL <-- QUEUE TOP ADDRESS
- EX$A41 EQU $
- MOV E,M ; LSB OF FRAME HEAD
- INX H
- MOV D,M ; MSB OF FRAME HEAD
- INX H
- SHLD AT$QR ; RECORD NEW POINTER
- XCHG ; HL <-- FRAME HEAD
- CALL LATQ3 ; SEND FEND
- JMP EXEC
-
-
-
-
-
- ; Here for timer expiration
- EX$A5 EQU $
- MVI B,0FFH-EXTI ; B <-- FLAG MASK
- DI ; GATE INTERRUPTS MOMENTARILY
- LDA EA$FLG ; A <-- END ACTION FLAGS
- ANA B ; MASK OUT EXTI
- STA EA$FLG ; WRITE FLAGS
- EI ; UNGATE
- LDA IT$STA ; A <-- STATE OF INTERVAL TIMER
- ORA A
- JZ A5$S0 ; IF (SLOT-TIME DELAY) GOTO A5$S0
- DCR A
- JZ A5$S1 ; IF (RELAY DELAY) GOTO A5$S1
- DCR A
- JZ A5$S2 ; IF (WATCH DOG) GOTO A5$S2
- DCR A
- JZ A5$S3 ; IF (SQUELCH DELAY) GOTO A5$S3
- JMP EXEC ; IGNORE INVALID STATES
-
- ; Slot-time is expired, if channel not busy, activate RTS
- A5$S0 EQU $
- LXI H,RPA ; HL <-- READ PORT A COMMAND
- CALL SCMDOT ; ISSUE COMMAND
- CALL SRSLIN ; READ RESULTS
- ANI MCD ; MASK MODEM CARRIER DETECT
- JNZ EXEC ; IF (CHANNEL BUSY) GOTO EXEC
- A5$S0A EQU $
- LXI H,SRDIS ; HL <-- SYNC. RCVR DISABLE COMMAND
- CALL SCMDOT ; ISSUE COMMAND
- LXI H,STRTS ; HL <-- SYNC. XMTR RTS ENABLE COMMAND
- CALL SCMDOT ; ISSUE COMMAND
- LDA RVAL ; A <-- RELAY DELAY VALUE
- MOV L,A ; COPY TO L
- XRA A
- MOV H,A ; EXTEND 16 BITS
- SHLD IT$VAL ; SET DELAY VALUE
- INR A ; A <-- 1
- STA IT$FLG ; ACTIVATE TIMER
- STA IT$STA ; RECORD NEW STATE
- LXI H,ST$QS ; HL <-- QUEUE SIZE POINTER
- DCR M ; DECREMENT COUNT
- LHLD ST$QR ; HL <-- QUEUE READ POINTER
- LXI D,-ST$QB ; DE <-- QUEUE BOTTOM ADDRESS
- PUSH H
- DAD D
- POP H
- JNC A5$S0B ; IF (NOT BOTTOM) GOTO A5$S0B
- LXI H,ST$QT ; HL <-- QUEUE TOP ADDRESS
- A5$S0B EQU $
- MOV A,M ; LSB OF FRAME SIZE
- STA STACT+2
- INX H ; ADVANCE POINTER
- MOV A,M ; MSB OF FRAME SIZE
- STA STACT+3
- INX H
- MOV E,M ; LSB OF FRAME HEAD
- INX H
- MOV D,M ; MSB OF FRAME HEAD
- INX H
- SHLD ST$QR ; WRITE NEW POINTER
- XCHG
- SHLD ST$BP ; ESTABLISH NEW FRAME POINTER
- JMP EXEC
-
- ; Relay delay time expired, start data transmission
- A5$S1 EQU $
- LXI H,STACT ; HL <-- SYNC. XMTR ACTIVATION COMMAND
- CALL SCMDOT ; ISSUE COMMAND
- LXI H,WDVAL ; HL <-- WATCHDOG TIMER VALUE
- SHLD IT$VAL ; RECORD IT
- MVI A,1
- STA IT$FLG ; ACTIVATE TIMER
- INR A ; NEW STATE
- STA IT$STA ; RECORD IT
- JMP EXEC
-
- ; Watchdog timer expiration, kill the transmitter
- A5$S2 EQU $
- LXI H,DARTS ; HL <-- DEACTIVATE RTS COMMAND
- CALL SCMDOT ; ISSUE COMMAND
- JMP INIT
-
- ; Squelch delay time expired, re-activate the sync. receiver
- A5$S3 EQU $
- LXI H,SRACT ; HL <-- SYNC. RCVR ACTIVATION COMMAND
- CALL SCMDOT ; ISSUE COMMAND
- JMP EXEC
-
-
-
-
-
- ; Here when synchronous receiver is discarding a frame
- ; because there are no available free cells.
- EX$A6 EQU $
- MVI B,0FFH-SRDD ; B <-- FLAG MASK
- DI ; GATE INTERRUPTS MOMENTARILY
- LDA EA$FLG ; A <-- END ACTION FLAGS
- ANA B ; MASK OUT SRDD
- STA EA$FLG ; WRITE FLAGS
- EI ; UNGATE
- LHLD SR$HC ; HL <-- FRAME HEAD
- CALL FCHN ; FREE THIS CHAIN
- LXI H,SRDIS ; HL <-- SYNC. RCVR DISABLE COMMAND
- CALL SCMDOT ; ISSUE COMMAND
- DI ; GATE INTERRUPTS MOMENTARILY
- CALL GCELL ; GET A FREE CELL
- EI ; UNGATE
- XCHG ; HL <-- CELL POINTER
- SHLD SR$BP ; ESTABLISH NEW BUFFER POINTERS
- SHLD SR$HC
- MVI M,0 ; RESET FORWARD POINTER
- INX H ; ADVANCE POINTER
- MVI M,0
- LXI H,SRACT ; HL <-- SYNC. RCVR ACTIVATION COMMAND
- CALL SCMDOT ; ISSUE COMMAND
- XRA A ; NEW STATE (RECORDING DATA)
- STA SR$STA ; RECORD IT
- JMP EXEC
-
-
-
-
-
- ; Here when asynchronous receiver is discarding a frame
- ; because there are no available free cells.
- EX$A7 EQU $
- MVI B,0FFH-ARDD ; B <-- FLAG MASK
- DI ; GATE INTERRUPTS MOMENTARILY
- LDA EA$FLG ; A <-- END ACTION FLAGS
- ANA B ; MASK OUT ARDD
- STA EA$FLG ; WRITE FLAGS
- EI ; UNGATE
- LHLD AR$HC ; HL <-- FRAME HEAD
- CALL FCHN ; FREE THIS CHAIN
- MVI A,ADTR+ARTS+OUT1 ; DTR, RTS, AND CD FOR HOST
- OUT MCR ; WRITE MODEM CONTROL REGISTER
- JMP EXEC
- PAGE
-
- ; Queue management routines for synchronous & asynchronous output
-
- ; Link a frame to the synchronous transmit queue
- LSTQ EQU $
- XCHG ; DE <-- ADDRESS OF FRAME
- LHLD ST$QW ; HL <-- QUEUE WRITE POINTER
- MOV M,C ; LSB OF FRAME SIZE
- INX H ; ADVANCE POINTER
- MOV M,B ; MSB OF FRAME SIZE
- INX H
- MOV M,E ; LSB OF FRAME HEAD
- INX H
- MOV M,D ; MSB OF FRAME HEAD
- INX H ; HL <-- NEXT QUEUE ENTRY
- LXI D,-ST$QB ; DE <-- QUEUE BOTTOM ADDRESS
- PUSH H ; PRESERVE HL
- DAD D
- POP H ; RESTORE QUEUE POINTER
- JNC LSTQ1 ; IF (NOT BOTTOM) GOTO LSTQ1
- LXI H,ST$QT ; HL <-- QUEUE TOP ADDRESS
- LSTQ1 EQU $
- SHLD ST$QW ; WRITE NEW QUEUE POINTER
- LXI H,ST$QS ; HL <-- QUEUE SIZE POINTER
- INR M ; INCREMENT QUEUE SIZE
- RET
-
-
-
-
-
- ; Link a frame to the asynchronous transmit queue
- LATQ EQU $
- LDA AT$QS ; A <-- QUEUE SIZE
- ORA A
- JNZ LATQ1 ; IF (QUEUED FRAMES) GOTO LATQ1
- LDA AT$STA ; A <-- STATE OF ASYNC. TRANSMITTER
- CPI 0FFH
- JZ LATQ3 ; IF (XMTR INACTIVE) GOTO LATQ3
- LATQ1 EQU $
- XCHG ; DE <-- ADDRESS OF FRAME
- LHLD AT$QW ; HL <-- QUEUE WRITE POINTER
- MOV M,E ; LSB OF FRAME HEAD
- INX H ; ADVANCE POINTER
- MOV M,D ; MSB OF FRAME HEAD
- INX H ; HL <-- NEXT QUEUE ENTRY
- LXI D,-AT$QB ; DE <-- QUEUE BOTTOM ADDRESS
- PUSH H ; PRESERVE HL
- DAD D
- POP H ; RESTORE QUEUE POINTER
- JNC LATQ2 ; IF (NOT BOTTOM) GOTO LATQ2
- LXI H,AT$QT ; HL <-- QUEUE TOP ADDRESS
- LATQ2 EQU $
- SHLD AT$QW ; WRITE NEW POINTER
- LXI H,AT$QS ; HL <-- QUEUE SIZE POINTER
- INR M ; INCREMENT QUEUE SIZE
- RET
- ; Queue is empty and asynchronous transmitter is
- ; inactive. Don't queue this entry, just send it out.
- LATQ3 EQU $
- SHLD AT$BP ; ESTABLISH NEW POINTER
- MVI A,FEND ; A <-- FEND
- OUT THR ; WRITE TRANSMIT HOLDING REGISTER
- MVI A,4 ; NEW STATE (OPENING FRAME)
- STA AT$STA ; RECORD IT
- MVI A,ERI+ETI+ELI+EMI ; 8250 INTERRUPT ENABLE FLAGS
- OUT IER ; WRITE INTERRUPT ENABLE REGISTER
- RET
- PAGE
-
- ; Buffer management routines
-
- ; Allocate a free cell
- GCELL EQU $
- LHLD FL$HC ; HL <-- HEAD CELL ON FREE LIST
- MOV A,H ; MSB OF ADDRESS
- ORA L ; LSB OF ADDRESS
- JZ GC$EL ; IF (EMPTY LIST) GOTO GC$EL
- XCHG ; DE <-- FREE CELL
- LXI H,FL$HC ; HL <-- HEAD CELL POINTER
- LDAX D ; A <-- LSB OF NEXT FREE CELL
- MOV M,A ; COPY TO FL$HC
- INX D ; ADVANCE POINTERS
- INX H
- LDAX D ; A <-- MSB OF NEXT FREE CELL
- MOV M,A ; COPY TO FL$HC
- DCX D ; RESET FREE CELL POINTER
- GC$EL EQU $
- RET
-
- ; Attach a cell to the free list
- FCELL EQU $
- LXI H,FL$HC ; HL <-- HEAD CELL POINTER
- MOV C,M ; C <-- LSB OF FIRST CELL
- MOV M,E ; UPDATE LSB OF FL$HC
- INX H ; ADVANCE POINTER
- MOV B,M ; B <-- MSB OF FIRST CELL
- MOV M,D ; UPDATE MSB OF FL$HC
- XCHG ; HL <-- RELEASED CELL
- MOV E,M ; E <-- LSB OF NEXT CELL
- MOV M,C ; COPY LSB OF OLD HC TO NEW
- INX H ; ADVANCE POINTER
- MOV D,M ; D <-- MSB OF NEXT CELL
- MOV M,B ; COPY MSB OF OLD HC TO NEW
- INX H ; ADVANCE POINTER
- MVI M,0 ; RESET NBYTE
- INX H
- MVI M,0 ; RESET NREAD
- XCHG ; HL <-- NEXT CELL IN CHAIN
- RET
-
- ; Attach a chain of cells to the free list
- FCHN EQU $
- XCHG ; DE <-- CELL TO BE RELEASED
- DI ; GATE INTERRUPTS MOMENTARILY
- CALL FCELL ; FREE IT UP
- EI ; UNGATE
- MOV A,H ; MSB OF FORWARD POINTER FROM CELL
- ORA L ; LSB OF SAME
- JNZ FCHN ; IF (MORE CELLS) GOTO FCHN
- RET
- PAGE
-
- ; Extract a character from the buffer referenced by HL
- GCHAR EQU $
- PUSH H ; PRESERVE HL
- INX H ; SKIP FORWARD POINTER
- INX H
- MOV A,M ; A <-- NBYTES
- INX H ; ADVANCE POINTER
- SUB M ; CHECK NREAD
- JZ GC$BE ; IF (BUFFER EXHAUSTED) GOTO GC$BE
- PUSH D ; PRESERVE DE
- INR M ; INCREMENT NREAD
- MOV E,M ; E <-- NREAD
- XRA A
- MOV D,A ; EXTEND 16 BITS
- DAD D ; HL <-- HL + DE
- INR A ; RESET 'Z' FLAG
- MOV A,M ; A <-- CHARACTER
- POP D ; RESTORE DE
- POP H ; RESTORE HL
- RET
- ; Follow chain to next buffer
- GC$BE EQU $
- POP H ; RESTORE HL
- PUSH D ; PRESERVE DE & BC
- PUSH B
- XCHG ; DE <-- BUFFER POINTER
- CALL FCELL ; RELEASE THIS CELL
- POP B ; RESTORE BC & DE
- POP D
- MOV A,H ; MSB OF NEXT CELL IN CHAIN
- ORA L ; LSB OF SAME
- JNZ GCHAR ; IF (GOOD BUFFER) GOTO GCHAR
- RET ; ELSE RETURN WITH 'Z' FLAG SET
-
- ; Stuff a character into the buffer referenced by HL
- PCHAR EQU $
- PUSH D ; PRESERVE DE
- PUSH PSW ; PRESERVE PSW (CHARACTER)
- INX H ; SKIP FORWARD POINTER
- INX H
- MVI A,124 ; A <-- BUFFER LIMIT
- SUB M ; A <-- 124 - NBYTES
- CZ PC$NB ; IF (NEED BUFFER) CALL PC$NB
- PUSH H ; PRESERVE HL (BUFFER POINTER)
- INR M ; INCREMENT NBYTES
- MOV E,M ; E <-- NBYTES
- XRA A
- MOV D,A ; EXTEND 16 BITS
- INX H ; SKIP NBYTES
- DAD D ; HL <-- HL + DE
- POP D ; RESTORE POINTER
- POP PSW ; RESTORE CHARACTER
- MOV M,A ; COPY CHARACTER TO BUFFER
- XCHG ; HL <-- ORIGINAL POINTER
- DCX H ; ADJUST POINTER
- DCX H
- POP D ; RESTORE DE
- XRA A
- INR A ; RESET 'Z' FLAG
- RET
- ; Here if PCHAR needs a new buffer
- PC$NB EQU $
- PUSH H ; PRESERVE HL
- CALL GCELL ; FREE CELL POINTER TO DE
- POP H ; RESTORE HL
- JZ PC$BF ; IF (BUFFERS FULL) GOTO PC$BF
- DCX H
- MOV M,D ; COPY MSB TO PREVIOUS CELL
- DCX H ; ADVANCE POINTER
- MOV M,E ; COPY LSB TO PREVIOUS CELL
- XCHG ; HL <-- NEW BUFFER POINTER
- MVI M,0 ; RESET FORWARD POINTER
- INX H ; ADVANCE POINTER
- MVI M,0
- INX H
- RET
- ; Here if free cell not available
- PC$BF EQU $
- POP PSW ; PURGE RETURN ADDRESS FROM STACK
- POP PSW ; RESTORE CHARACTER
- POP D ; RESTORE DE
- XRA A ; SET 'Z' FLAG
- RET
- PAGE
-
- ; Asynchronous Interrupt Response Code
-
- AIRC EQU $
- PUSH PSW ; SAVE PROGRAM STATUS WORD
- IN IIR ; READ INTERRUPT IDENTIFICATION REG.
- RAR ; RIGHT JUSTIFY ID BITS
- ANI 00000011B ; MASK
- JZ IRC$AM ; IF (MODEM STATUS) GOTO IRC$AM
- DCR A
- JZ IRC$AT ; IF (XMTR EMPTY) GOTO IRC$AT
- DCR A
- JZ IRC$AR ; IF (DATA READY) GOTO IRC$AR
-
-
-
-
-
- ; Here for line status interrupt
- IRC$AL EQU $
- IN LSR ; READ LINE STATUS REGISTER
- ANI BI ; MASK BREAK INTERRUPT
- ; Treat overrun, parity, framing errors as data ready
- JZ IRC$AR ; IF (NOT BI) GOTO IRC$AR
- IN RBR ; FLUSH NULL FROM BUFFER
- POP PSW ; RESTORE PSW
- EI ; UNGATE
- RET ; RETURN FROM INTERRUPT
-
-
-
-
-
- ; Here for modem status interrupt
- IRC$AM EQU $
- IN MSR ; READ MODEM STATUS
- PUSH PSW ; SAVE STATUS
- ANI DCTS+DDSR ; MASK SOURCE BITS OF INTEREST
- RAR
- RAR
- JM AM$1 ; IF (DELTA CTS) GOTO AM$1
- JC INIT ; IF (HOST LOST) GOTO INIT
-
- IF TNCPLUS
- POP PSW ; Get status back from stack
- ANI TERI ; Ring indicate trailing edge?
- JZ TICKX ; No, go to return from interrupt
- LDA TICKCNT ; Increment tick count
- INR A
- STA TICKCNT
- TICKX: POP PSW
- EI
- RET
- ELSE
- ; Ignore other sources of this interrupt
- POP PSW ; REMOVE STATUS FROM STACK
- POP PSW
- EI
- RET ; RETURN FROM INTERRUPT
- ENDIF
-
- ; Here if Clear-To-Send has changed state
- AM$1 EQU $
- POP PSW ; FETCH MODEM STATUS FROM STACK
- ANI TCTS ; MASK TERMINAL CLEAR-TO-SEND STATUS
- JNZ AM$2 ; IF (CLEAR-TO-SEND) GOTO AM$2
- ; Host has full buffer or something, stop sending
- MVI A,ERI+ELI+EMI ; INTERRUPT ENABLE FLAGS
- OUT IER ; WRITE INTERRUPT ENABLE REGISTER
- POP PSW
- EI
- RET ; RETURN FROM INTERRUPT
- ; Host is now ready to receive data again
- AM$2 EQU $
- LDA AT$STA ; A <-- STATE OF TRANSMITTER
- CPI 0FFH
- JZ AM$3 ; IF (INACTIVE) GOTO AM$3
- MVI A,ERI+ETI+ELI+EMI ; INTERRUPT ENABLE FLAGS
- OUT IER ; WRITE INTERRUPT ENABLE REGISTER
- AM$3 EQU $
- POP PSW
- EI
- RET ; RETURN FROM INTERRUPT
-
-
-
-
-
- ; Here for asynchronous transmit interrupt
- IRC$AT EQU $
- LDA AT$STA ; A <-- STATE OF TRANSMITTER
- ORA A
- JZ AT$S0 ; IF (NOT ESCAPED) GOTO AT$S0
- DCR A
- JZ AT$S1 ; IF (SENDING TFESC) GOTO AT$S1
- DCR A
- JZ AT$S2 ; IF (SENDING TFEND) GOTO AT$S2
- DCR A
- JZ AT$S3 ; IF (END OF FRAME) GOTO AT$S3
- DCR A
- JZ AT$S4 ; IF (OPENING FRAME) GOTO AT$S4
- JMP RST1+1 ; IGNORE INACTIVE STATE
-
- IF TNCPLUS
- ; ENTER HERE TO RETURN FROM AN INTERRUPT. THE FIRST
- ; ITEM ON THE STACK WILL BE A RETURN ADDRESS TO THE
- ; RST INSTRUCTION WHICH GOT US HERE SO IT GETS WASTED.
- ; NEXT THE PROGRAM STATUS WORD (ACCUMULATOR & FLAGS)
- ; ARE RESTORE, INTERRUPTS ARE RE-ENABLED AND THE REST
- ; IS HISTORY.
-
- RST1 EQU $
- POP PSW ; PURGE BOGUS ADDRESS FROM STACK
- POP PSW ; RESTORE PROGRAM STATUS WORD
- EI ; UNGATE INTERRUPTS
- RET ; RETURN TO POINT OF INTERRUPT
- ENDIF
-
- ; Here for normal data transmission (not currently escaped)
- AT$S0 EQU $
- PUSH H ; PRESERVE HL
- LHLD AT$BP ; HL <-- BUFFER POINTER
- CALL GCHAR ; MOVE NEXT CHARACTER TO A
- SHLD AT$BP ; SAVE UPDATED POINTER
- POP H ; RESTORE HL
- JZ AT$S0S3 ; IF (END OF FRAME) GOTO AT$S0S3
- CPI FESC
- JZ AT$S0S1 ; IF (CHAR = FESC) GOTO AT$S0S1
- CPI FEND
- JZ AT$S0S2 ; IF (CHAR = FEND) GOTO AT$S0S2
- OUT THR ; WRITE CHARACTER
- POP PSW
- EI
- RET ; RETURN FROM INTERRUPT
- ; Send FESC and change state to 1
- AT$S0S1 EQU $
- OUT THR ; WRITE FESC
- MVI A,1 ; NEW STATE
- STA AT$STA ; RECORD NEW STATE
- POP PSW
- EI
- RET ; RETURN FROM INTERRUPT
- ; Send FESC and change state to 2
- AT$S0S2 EQU $
- MVI A,FESC ; A <-- FESC
- OUT THR ; WRITE
- MVI A,2 ; NEW STATE
- STA AT$STA ; RECORD NEW STATE
- POP PSW
- EI
- RET ; RETURN FROM INTERRUPT
- ; Send FEND and change state to 3
- AT$S0S3 EQU $
- MVI A,FEND ; A <-- FEND
- OUT THR ; WRITE
- MVI A,3 ; NEW STATE
- STA AT$STA ; RECORD NEW STATE
- POP PSW
- EI
- RET ; RETURN FROM INTERRUPT
-
- ; Send TFESC (FESC was last character sent)
- AT$S1 EQU $
- MVI A,TFESC ; A <-- TFESC
- OUT THR ; WRITE
- XRA A ; NEW STATE (NOT ESCAPED)
- STA AT$STA ; RECORD NEW STATE
- POP PSW
- EI
- RET ; RETURN FROM INTERRUPT
-
- ; Send TFEND (FESC was last character sent)
- AT$S2 EQU $
- MVI A,TFEND ; A <-- TFEND
- OUT THR ; WRITE
- XRA A ; NEW STATE (NOT ESCAPED)
- STA AT$STA ; RECORD NEW STATE
- POP PSW
- EI
- RET ; RETURN FROM INTERRUPT
-
- ; Here for end of frame transmission - FEND already sent
- AT$S3 EQU $
- MVI A,ERI+ELI+EMI ; RCVR, LINE, AND MODEM ENABLE FLAGS
- OUT IER ; WRITE INTERRUPT ENABLE REGISTER
- LDA EA$FLG ; A <-- END ACTION FLAGS
- ORI ATFC ; SET ASYNC. XMTR FRAME COMPLETE
- STA EA$FLG ; WRITE FLAGS
- MVI A,0FFH ; NEW STATE (ASYNC. XMTR DISABLED)
- STA AT$STA ; RECORD IT
- POP PSW
- EI
- RET
-
- ; Here for opening frame, send data frame control byte
- AT$S4 EQU $
- XRA A ; A <-- 0
- OUT THR ; WRITE CONTROL BYTE
- STA AT$STA ; ALSO IS OUR NEW STATE
- POP PSW
- EI
- RET
-
-
-
-
- ; Here for asynchronous receive interrupt
- IRC$AR EQU $
- LDA AR$STA ; A <-- STATE OF RECEIVER
- ORA A
- JZ AR$S0 ; IF (EXPECTING DATA) GOTO AR$S0
- DCR A
- JZ AR$S1 ; IF (ESCAPED) GOTO AR$S1
- DCR A
- JZ AR$S2 ; IF (EXPECTING COMMAND) GOTO AR$S2
- DCR A
- JZ AR$S3 ; IF (EXPECTING P-VALUE) GOTO AR$S3
- DCR A
- JZ AR$S4 ; IF (EXPECTING S-VALUE) GOTO AR$S4
- DCR A
- JZ AR$S5 ; IF (EXPECTING T-VALUE) GOTO AR$S5
- DCR A
- JZ AR$S6 ; IF (EXPECTING TXDELAY) GOTO AR$S6
-
- ; Here if waiting for FEND to begin a new frame
- AR$S7 EQU $
- IN RBR ; READ CHARACTER
- CPI FEND
- JNZ RST1+1 ; IF (NOT FEND) RETURN FROM INTERRUPT
- MVI A,2 ; NEW STATE
- STA AR$STA ; RECORD NEW STATE
- POP PSW
- EI
- RET ; RETURN FROM INTERRUPT
-
- ; Here if expecting frame data
- AR$S0 EQU $
- IN RBR ; READ CHARACTER
- CPI FESC
- JZ AR$S0S1 ; IF (DATA = FESC) GOTO AR$S0S1
- CPI FEND
- JZ AR$S0S2 ; IF (DATA = FEND) GOTO AR$S0S2
- PUSH H ; PRESERVE HL
- LHLD AR$BP ; HL <-- BUFFER POINTER
- CALL PCHAR ; STORE CHARACTER
- JZ AR$S0S7 ; IF (BUFFERS FULL) GOTO AR$S0A
- SHLD AR$BP ; RECORD NEW POINTER
- LHLD AR$FSZ ; HL <-- FRAME SIZE
- INX H ; INCREMENT COUNT
- SHLD AR$FSZ ; RECORD IT
- POP H ; RESTORE HL
- POP PSW
- EI
- RET ; RETURN FROM INTERRUPT
- ; Here we deal with a serious problem. We are in the middle
- ; of a frame and filled our current buffer, but alas, there
- ; are no free cells to allocate. Return all buffers in this
- ; frame to the free cell list and hope we recover.
- AR$S0S7 EQU $
- AR$S1S7 EQU $
- LDA EA$FLG ; A <-- END ACTION FLAGS
- ORI ARDD ; ASYNC. RECEIVER DISCARDING DATA
- STA EA$FLG ; SAVE UPDATED FLAGS
- MVI A,ADTR+OUT1 ; DTR & CD, NO RTS
- OUT MCR ; WRITE MODEM CONTROL REGISTER
- POP H ; RESTORE HL
- ; Here we just change state to wait for the next incoming
- ; frame and hope by then that we have recovered some cells.
- AR$S2S7 EQU $
- MVI A,7 ; NEW STATE
- STA AR$STA ; RECORD NEW STATE
- POP PSW
- EI
- RET ; RETURN FROM INTERRUPT
- ; FESC was just detected. Change state to 1 and see what follows.
- AR$S0S1 EQU $
- MVI A,1 ; NEW STATE
- STA AR$STA ; RECORD IT
- POP PSW
- EI
- RET ; RETURN FROM INTERRUPT
- ; FEND was just detected. Move frame to synch. transmit queue.
- AR$S0S2 EQU $
- PUSH H ; PRESERVE HL
- LHLD AR$HC ; HL <-- HEAD CELL POINTER
- SHLD AR$FH ; SAVE POINTER FOR EXEC
- LHLD AR$FSZ ; HL <-- FRAME SIZE
- SHLD AR$FS ; SAVE FOR EXECUTIVE
- MVI A,2 ; NEW STATE
- STA AR$STA ; RECORD IT
- LDA EA$FLG ; A <-- END ACTION FLAGS
- ORI ARFC ; ASYNC. RECEIVER FRAME COMPLETE
- STA EA$FLG ; SAVE UPDATED FLAGS
- MVI A,ADTR+OUT1 ; DTR & CD, NO RTS
- OUT MCR ; WRITE MODEM CONTROL REGISTER
- POP H ; RESTORE HL
- POP PSW
- EI
- RET ; RETURN FROM INTERRUPT
-
- ; This character follows an FESC, must be TFESC or TFEND
- AR$S1 EQU $
- XRA A ; NEW STATE
- STA AR$STA ; RECORD IT
- IN RBR ; READ CHARACTER
- CPI TFESC
- JZ AR$S1A ; IF (DATA = TFESC) GOTO AR$S1A
- CPI TFEND
- JNZ RST1+1 ; IF (DATA <> TFEND) RETURN FROM INT.
- ; Character was TFEND. Translate it.
- MVI A,FEND ; A <-- FEND
- JMP AR$S1B ; STORE IT
- ; Character was TFESC. Translate it.
- AR$S1A EQU $
- MVI A,FESC ; A <-- FESC
- AR$S1B EQU $
- PUSH H ; PRESERVE HL
- LHLD AR$BP ; HL <-- BUFFER POINTER
- CALL PCHAR ; STORE CHARACTER
- JZ AR$S1S7 ; IF (BUFFERS FULL) GOTO AR$S1S7
- SHLD AR$BP ; RECORD NEW POINTER
- LHLD AR$FSZ ; HL <-- FRAME SIZE
- INX H ; INCREMENT COUNT
- SHLD AR$FSZ ; RECORD IT
- POP H ; RESTORE HL
- POP PSW
- EI
- RET ; RETURN FROM INTERRUPT
-
- ; Last character seen was FEND. Look for frame command.
- AR$S2 EQU $
- IN RBR ; READ CHARACTER
- CPI FEND
- JZ RST1+1 ; RETURN FROM INTERRUPT
- ORA A
- JZ AR$S2S0 ; IF (DATA FRAME) GOTO AR$S2S0
- DCR A
- JZ AR$S2A ; IF (R COMMAND) GOTO AR$S2A
- DCR A
- JZ AR$S2B ; IF (P COMMAND) GOTO AR$S2B
- DCR A
- JZ AR$S2C ; IF (S COMMAND) GOTO AR$S2C
- DCR A
- JZ AR$S2D ; IF (T COMMAND) GOTO AR$S2D
- JMP AR$S2S7 ; BOGUS COMMAND, WAIT FOR FEND
- ; Here if TxDelay value to follow
- AR$S2A EQU $
- MVI A,6 ; NEW STATE
- STA AR$STA ; RECORD IT
- POP PSW
- EI
- RET ; RETURN FROM INTERRUPT
- ; Here if Persistence value to follow
- AR$S2B EQU $
- MVI A,3
- STA AR$STA
- POP PSW
- EI
- RET
- ; Here if Slot-time value to follow
- AR$S2C EQU $
- MVI A,4
- STA AR$STA
- POP PSW
- EI
- RET
- ; Here if Squelch-delay value to follow
- AR$S2D EQU $
- MVI A,5
- STA AR$STA
- POP PSW
- EI
- RET
- ; Here when data to follow
- AR$S2S0 EQU $
- PUSH H ; PRESERVE HL
- CALL GCELL ; GET A FREE CELL
- JZ AR$S2S7 ; IF (BUFFERS FULL) GOTO AR$S0S7
- XCHG ; HL <-- CELL POINTER
- SHLD AR$BP ; ESTABLISH NEW BUFFER POINTERS
- SHLD AR$HC
- MVI M,0 ; RESET FORWARD POINTER
- INX H ; ADVANCE POINTER
- MVI M,0
- LXI H,0 ; HL <-- 0
- SHLD AR$FSZ ; RESET FRAME SIZE
- POP H ; RESTORE HL
- XRA A ; NEW STATE
- STA AR$STA ; RECORD IT
- POP PSW
- EI
- RET ; RETURN FROM INTERRUPT
-
- ; Load a persistence value
- AR$S3 EQU $
- IN RBR
- STA PVAL
- MVI A,2
- STA AR$STA
- POP PSW
- EI
- RET
-
- ; Load a slot-time value
- AR$S4 EQU $
- IN RBR
- STA SVAL
- MVI A,2
- STA AR$STA
- POP PSW
- EI
- RET
-
- ; Load a squelch-delay value
- AR$S5 EQU $
- IN RBR
- STA TVAL
- MVI A,2
- STA AR$STA
- POP PSW
- EI
- RET
-
- ; Load a Tx relay delay value
- AR$S6 EQU $
- IN RBR
- STA RVAL
- MVI A,2
- STA AR$STA
- POP PSW
- EI
- RET
- PAGE
-
- ; Synchronous Transmitter Interrupt Response Code
-
- STIRC EQU $
- PUSH PSW ; PRESERVE PROGRAM STATUS WORD
- PUSH H ; SAME WITH HL
- IN STAT73 ; READ STATUS
- mov a,l ; save status
- ani txintp ; test tx interrupt bit
- jnz stirc1 ; jump if interrupt appears normal
- ; Here for an unexpected interrupt
- lhld txicnt ; fetch error counter
- inx h ; count this error
- shld txicnt ;
- push d
- push b
- call init73 ; Re-initialise the 8273
- jmp exit ; Exit from the interrupt
-
- ; Here for normal tx interrupt
- stirc1: mov a,l ; Restore 8273 status
- ANI TXIRA
- JNZ ST$CI ; IF (END-OF-FRAME) GOTO ST$CI
- ; Here if transmitter waiting for data
- LHLD ST$BP ; HL <-- BUFFER POINTER
- CALL GCHAR ; MOVE NEXT CHARACTER TO A
- OUT TXDR73 ; WRITE CHARACTER
- SHLD ST$BP ; SAVE UPDATED POINTER
- POP H ; RESTORE HL
- POP PSW
- EI
- RET ; RETURN FROM INTERRUPT
-
- ; Here for frame completion interrupt
- ST$CI EQU $
- IN TXIR73 ; READ RESULTS
- STA ST$FR ; SAVE RESULTS POINTER
- PUSH D ; PRESERVE DE
- LHLD ST$BP ; HL <-- CURRENT BUFFER POINTER
- XCHG ; MOVE POINTER TO DE
- CALL FCELL ; FREE THIS CELL
- POP D ; RESTORE DE
- LDA EA$FLG ; A <-- END ACTION FLAGS
- ORI STFC ; SYNC. TRANSMITTER FRAME COMPLETE
- STA EA$FLG ; SAVE UPDATED FLAGS
- POP H ; RESTORE HL
- POP PSW
- EI
- RET ; RETURN FROM INTERRUPT
- PAGE
-
- EXIT pop b ; Restore registers
- pop d ;
- pop h ;
- pop psw ; Restore PSW
- ei ; Enable Interrupts
- ret ; Return to interrupted code
-
-
- ; Synchronous Receiver Interrupt Response Code
-
- SRIRC EQU $
- PUSH PSW ; PRESERVE PROGRAM STATUS WORD
- LDA SR$STA ; A <-- STATE OF SYNC. RECEIVER
- ORA A
- JNZ SR$S1 ; IF (DISCARDING DATA) GOTO SR$S1
-
- ; Here if synchronous receiver state 0, recording data
- SR$S0 EQU $
- PUSH H ; PRESERVE HL
- IN STAT73 ; READ STATUS
- mov a,l ; save status
- ani rxintp ; test rx interrupt bit
- jnz sr$s01 ; jump if interrupt appears normal
- ; Here for an unexpected interrupt
- lhld rxicnt ; fetch error counter
- inx h ; count this error
- shld rxicnt ;
- push d
- push b
- call init73 ; Re-initialise the 8273
- jmp exit ; Exit from the interrupt
-
- ; Here for normal rx interrupt
- sr$s01: mov a,l ; Restore 8273 status
- ANI RXIRA
- JNZ SR$CI ; IF (END-OF-FRAME) GOTO SR$CI
- ; Here if receiver has data to unload
- IN RXDR73 ; READ CHARACTER
- LHLD SR$BP ; HL <-- BUFFER POINTER
- CALL PCHAR ; COPY CHARACTER TO BUFFER
- JZ SR$BF ; IF (BUFFERS FULL) GOTO SR$BF
- SHLD SR$BP ; SAVE UPDATED POINTER
- POP H ; RESTORE HL
- POP PSW
- EI
- RET ; RETURN FROM INTERRUPT
-
- ; Here for frame completion interrupt
- SR$CI EQU $
- IN RXIR73 ; READ FRAME STATUS
- STA SR$FR ; SAVE IT FOR EXEC
- PUSH B ; PRESERVE BC
- MVI B,20 ; TIMOUT
-
- SR$CIA EQU $
- IN STAT73 ; READ STATUS
- ANI RINTP
- JZ SR$CIB ; IF (RESULTS COMPLETE) GOTO SR$CIB
- IN STAT73 ; READ 8273 STATUS AGAIN
- ANI RXIRA
- JNZ SR$CIC ; Go to read result
- DCR B ; Decrement timeout
- JNZ SR$CIA ; Continue testing
- CALL INIT73
- POP B
- POP H
- POP PSW
- EI
- RET
-
- ; Ready to read one byte of results code
- SR$CIC: IN RXIR73 ; READ RESULTS
- JMP SR$CIA ; WAIT FOR MORE, IF ANY
- ; Results are now complete
- SR$CIB EQU $
- LDA EA$FLG ; A <-- END ACTION FLAGS
- ORI SRFC ; SYNC. RECEIVER FRAME COMPLETE
- STA EA$FLG ; SAVE UPDATED FLAGS
- POP B ; RESTORE BC
- POP H ; RESTORE HL
- POP PSW
- EI
- RET ; RETURN FROM INTERRUPT
- ; Again we must deal with being in the middle of a frame
- ; with no available free cells to continue. Release the
- ; cells for this frame and cease reception till we recover.
- SR$BF EQU $
- MVI A,1 ; NEW STATE
- STA SR$STA ; RECORD IT
- LDA EA$FLG ; A <-- END ACTION FLAGS
- ORI SRDD ; SYNC. RECEIVER DISCARDING DATA
- STA EA$FLG ; SAVE UPDATED FLAGS
- POP H ; RESTORE HL
- POP PSW
- EI
- RET ; RETURN FROM INTERRUPT
-
- ; Here if synchronous receiver state 1, discarding data
- SR$S1 EQU $
- IN STAT73 ; READ STATUS
- mov a,l ; save status
- ani rxintp ; test rx interrupt bit
- jnz sr$s11 ; jump if interrupt appears normal
- ; Here for an unexpected interrupt
- lhld rxicnt ; fetch error counter
- inx h ; count this error
- shld rxicnt ;
- push d
- push b
- call init73 ; Re-initialise the 8273
- jmp exit ; Exit from the interrupt
-
- ; Here for normal rx interrupt
- sr$s11: mov a,l ; Restore 8273 status
- ANI RXIRA
- JNZ SR$DR ; IF (END-OF-FRAME) GOTO SR$DR
- ; Here if receiver has data to unload
- IN RXDR73 ; READ CHARACTER
- POP PSW
- EI
- RET ; RETURN FROM INTERRUPT
- ; Here if discarding results
- SR$DR EQU $
- IN RXIR73 ; READ FRAME RESULTS
- PUSH H
- PUSH B ; PRESERVE BC
- mvi b,20 ; Timeout
- SR$DRA EQU $
- IN STAT73 ; READ STATUS
- ANI RINTP
- JZ SR$DRB ; IF (RESULTS COMPLETE) GOTO SR$DRB
- IN STAT73 ; Read 8273 status again
- ANI RXIRA
- JNZ SR$DRC
- DCR B
- JNZ SR$DRA ; IF (NO RESULTS) GOTO SR$DRA
- CALL INIT73
- POP B
- POP H
- POP PSW
- EI
- RET
-
- ; Ready to read one byte of results code
- SR$DRC: IN RXIR73 ; READ RESULTS
- JMP SR$DRA ; WAIT FOR MORE, IF ANY
- ; Results are now complete
- SR$DRB EQU $
- POP B ; RESTORE BC
- POP H
- POP PSW
- EI
- RET ; RETURN FROM INTERRUPT
- PAGE
- **************************************************************************
- RESET73:MVI A,1 ; Reset 8273
- OUT TEST73
- XCHG ; Delay
- XCHG
- XRA A
- OUT TEST73 ; End of reset
- RET
- **************************************************************************
- INIT73: CALL RESET73
- ; Synchronous controller activation follows
- LXI H,DTRANS
- CALL SCMDOT ; SET DATA XFER MODE
- LXI H,OPMODE
- CALL SCMDOT ; SET OPERATING MODE
- LXI H,SERIO
- CALL SCMDOT ; SET SERIAL I/O MODE
- LXI H,SSDTR
- JMP SCMDOT ; SET SYNCH. DTR TO MODEM
- ***************************************************************************
-
- ; Command and Immediate Results routines for 8273
-
- SCMDOT: EQU $
- MOV B,M ; B <-- PARAMETER COUNT
- INX H ; ADVANCE TO COMMAND BYTE
- CMD1 EQU $
- IN STAT73 ; READ STATUS
- RLC ; MOVE CBSY INTO CARRY
- JC CMD1 ; IF (CBSY <> 0) GOTO CMD1
- MOV A,M ; A <-- COMMAND BYTE
- OUT CMND73 ; WRITE COMMAND
- CMD2 EQU $
- MOV A,B ; A <-- PARAMETER COUNT
- ANA A
- RZ ; IF (COUNT = 0) RETURN
- INX H ; ADVANCE POINTER
- DCR B ; DECREMENT PARAMETER COUNT
- CMD3 EQU $
- IN STAT73 ; READ STATUS
- ANI CPBF ; MASK COMMAND PARAMETER BUFFER FULL
- JNZ CMD3 ; IF (CPBF <> 0) GOTO CMD3
- MOV A,M ; A <-- PARAMETER
- OUT PARM73 ; WRITE PARAMETER
- JMP CMD2 ; CHECK FOR MORE PARAMETERS
-
-
-
- SRSLIN EQU $
- IN STAT73 ; READ STATUS
- ANI CRBF ; MASK COMMAND RESULTS BUFFER FULL
- JZ SRSLIN ; IF (CRBF = 0) GOTO SRSLIN
- IN RESL73 ; READ RESULTS
- RET
- PAGE
-
- ; Messages
-
- ;
- ; TNC's SIGNATURE
- TNCID EQU $
- DB 'VADCG/ASHBY-2716 Terminal Node Controller'
- DB CR,LF
- DB 'KISS Protocol Firmware Version 1.03 08 FEB 87'
- DB CR,LF,LF
-
- ;
- ; COMMAND SEQUENCES FOR 8273 CONTROLLER
- DTRANS DB 1,97H,1
- OPMODE DB 1,91H,03H
- SERIO DB 1,0A0H,1
- SSDTR DB 1,0A3H,4
- STRTS DB 1,0A3H,1
- DARTS DB 1,63H,0FEH
- SRDIS DB 0,0C5H
- RPA DB 0,22H
-
- END
-
-